package com.jason.www.commons;

import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.ExceptionHandler;
import com.lmax.disruptor.TimeoutException;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.log4j.Logger;

import java.util.concurrent.TimeUnit;

/**
 * @author ybd
 * @date 18-9-29
 * @contact yangbingdong1994@gmail.com
 */
public final class DisruptorUtil {
    private static Logger logger = Logger.getLogger(DisruptorUtil.class);

    public static BasicThreadFactory getThreadFactory() {
        return new BasicThreadFactory.Builder().namingPattern("disruptor-%d")
                                               .daemon(true)
                                               .build();
    }

    public static <T> Disruptor<T> createDisruptor(EventFactory<T> eventFactory, int bufferSize) {
        Disruptor<T> disruptor = new Disruptor<>(eventFactory, bufferSize, getThreadFactory(), ProducerType.SINGLE, new BlockingWaitStrategy());
        disruptor.setDefaultExceptionHandler(new DefaultDisruptorExceptionHandler<>());
        return disruptor;
    }

    public static void shutDownDisruptor(Disruptor disruptor) {
        if (disruptor != null) {
            try {
                disruptor.shutdown(5, TimeUnit.SECONDS);
            } catch (TimeoutException e) {
                logger.error("Disruptor shutdown error!", e);
            }
        }
    }

    public static class DefaultDisruptorExceptionHandler<T> implements ExceptionHandler<T> {
        private static Logger logger = Logger.getLogger(DefaultDisruptorExceptionHandler.class);
        @Override
        public void handleEventException(Throwable ex, long sequence, T event) {
            logger.error(event.getClass().getSimpleName() + " handler error:", ex);
        }

        @Override
        public void handleOnStartException(Throwable ex) {
            logger.error("handler start error", ex);
        }

        @Override
        public void handleOnShutdownException(Throwable ex) {
            logger.error("handler shutdown error", ex);
        }
    }

}
